﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Globalization;
using Styx.Common;
using System.Diagnostics;
using Styx.WoWInternals.WoWObjects;
using Styx;
using Styx.CommonBot;
using System.Windows.Forms;
using System.Windows.Media;

using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;
using CommonBehaviors;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.WoWInternals;
using CommonBehaviors.Actions;
using Bots.Gatherbuddy;
using System.IO;
using System.Net;

namespace PetFighterBot
{
    public class PetFighter : BotBase
    {
        #region Nothing to see here!
        public static readonly Version _Version = new Version(1, 1, 0);
        public override string Name { get { return "[PetFighter] v" + _Version; } }
        public override PulseFlags PulseFlags { get { return PulseFlags.All; } }
        public override Form ConfigurationForm { get { return new SettingsForm(); } }
        #endregion

        #region variables

        private PokehbuddygApi _PokehbuddygApi;
        private bool startUp = true;
        private int startUpCount = 0;
        private Composite _root { get; set; }
        private static LocalPlayer Me { get { return StyxWoW.Me; } }
        public static string ForumLink { get { return "http://www.thebuddyforum.com/honorbuddy-forum/plugins/uncataloged/81211-botbase-petfighter-your-honorbuddy-bot-petbattle.html"; } }
        //private Stopwatch waitTimer = new Stopwatch();
        public WoWSpell ReviveBattlePets; // SpellID 125439 Haustiere beleben
        private DateTime startTime = DateTime.Now;
        //http://www.wowhead.com/item=86143 verbände
        private string CombatLogPatch = string.Empty;
        private bool giveUp = false;
        private bool hasSwap = false;
        public bool _MixedMode = false;
        private int Battle_WON, Battle_lost, Round, BlacklistCounter;
        public static bool NewRound = false;

        private BBSettings _BBSettings { get { return new BBSettings(Application.StartupPath + "\\Plugins\\Pokehbuddy\\Pokehbuddy.xml"); } }
        private static Stopwatch timer = new Stopwatch();
        private int pvptimer;

        public Thread UpdateThread { get { return new Thread(checkUpdates) { IsBackground = true, Name = "PetFighter UpdateThread" }; } }        
        //public static PetFighter Instance;
        //public PetFighter()
        //{ Instance = this; }
        #endregion

        #region sloging
        public static void slog(Color color, string format, params object[] args)
        { Logging.Write(color, "[PetFighter]: " + format, args); }

        public static void slog(string format, params object[] args)
        { slog(Colors.Goldenrod, format, args); }

        public static void dlog(string format, params object[] args)
        {
            CultureInfo oldCI = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
            Logging.WriteDiagnostic(Colors.Firebrick, DateTime.Now.ToLongTimeString() + " [PetFighter]: " + format, args);
            Thread.CurrentThread.CurrentCulture = oldCI;
        }

        //public void flog(bool newBattle, string format, params object[] args)
        //{ CombatRoutineHelpers.flog(newBattle, string.Format(format, args)); }
        #endregion

        #region MixedMode
        public override bool IsPrimaryType
        { get { return false; } }

        public override bool RequirementsMet
        {
            get
            {
                _MixedMode = true;
                if (PetBattle.IsInPetBattle)
                    return true;

                if (Me.Combat)
                {
                    if (Me.CurrentTargetGuid != 0 && Me.CurrentTarget.IsPetBattleCritter)
                        Me.ClearTarget();
                    return false;
                }

                if (PetFighterSettings.Instance.PetBattle_Wild && PetFighterSettings.Instance.autoRevive && NeedRevival && SpellManager.CanCast(ReviveBattlePets))
                    return true;

                if (_BBSettings.DoPVP)
                {
                    if (PetBattle.GetPVPMatchmakingInfo == null && PetBattleStateByName == "wait")
                    { slog("start PvP Matchmaking!"); PetBattle.StartPVPMatchmaking(); Thread.Sleep(1000); }

                    if (PetBattle.GetPVPMatchmakingInfo == "proposal")
                    {
                        TimeSpan _rnd = TimeSpan.FromMilliseconds(new Random().Next(1000, 3500));
                        slog(Colors.OrangeRed, "new PetBattle available! Accept match in {0}sec .. ", _rnd.TotalSeconds); 
                        Thread.Sleep(_rnd);
                        PetBattle.AcceptQueuedPVPMatch();
                        Thread.Sleep(800);
                        return true;
                    }
                }

                if (PetFighterSettings.Instance.PetBattle_Wild && !NeedRevival && NextPetBattleCritter && 
                    (!PetFighterSettings.Instance.autoRevive || !NeedRevival))
                    return true;


                return false;
            }
        }
        #endregion

        public override void Initialize()
        {
            //PokehbuddygApi _PokehbuddygApi = new PokehbuddygApi();

            //if (PetFighterSettings.Instance.CheckForUpdates)  // move to root
            //{
            //    TimeSpan ts = (DateTime.Now - DateTime.FromBinary(PetFighterSettings.Instance.LastUpdateCheck));
            //    if (ts.TotalHours >= 12 && !UpdateThread.IsAlive)
            //    {
            //        slog("Checking for Updates..");
            //        UpdateThread.Start();
            //    }
            //}

        }

        public override void Start()
        {
            _PokehbuddygApi = new PokehbuddygApi();
            string error = string.Empty;
            if (!_PokehbuddygApi.HasPokehbuddy())
            {
                string txt = "Please install the Plugin [Pokébuddy]";
                Logging.Write(System.Windows.Media.Colors.Firebrick, txt + "\n visit:\n http://www.thebuddyforum.com/honorbuddy-forum/plugins/uncataloged/81355-plugin-pok-buddy-gotto-kill-em-all.html");
                MessageBox.Show(txt, "error", MessageBoxButtons.OK, MessageBoxIcon.Error); error = txt;
            }

            if (error != string.Empty)
                TreeRoot.Stop(error);

            if (!File.Exists(XmlHelper.StableMaster_Patch))
                File.Copy(Application.StartupPath + "\\Bots\\PetFighter\\Includes\\Stablemaster_backup.xml", XmlHelper.StableMaster_Patch);

            CombatLogPatch = Application.StartupPath + "\\Logs\\PetFighter\\CombatLog_" + DateTime.Now.ToShortDateString() + "_" + DateTime.Now.ToShortTimeString() + ".txt";
            
            if (BotManager.Current.Name == "MixedMode")
                startUp = false;

            Lua.Events.AttachEvent("PET_BATTLE_PET_ROUND_RESULTS", RoundResultEvent);

            //BotEvents.OnBotStop += stopBot;
            //BotEvents.OnBotStart += startBot;

            ReviveBattlePets = WoWSpell.FromId(125439);



            if (!_MixedMode)
            {
                slog("");
                slog("v{0} starting ({1})", _Version, Thread.CurrentThread.CurrentCulture.Name);
                slog("PetBattle_Wild: {0}", PetFighterSettings.Instance.PetBattle_Wild);
                if (PetFighterSettings.Instance.PetBattle_Wild)
                {
                    slog("   - LevelMode: {0}", PetFighterSettings.Instance.LevelMode);
                    ProfileHelper.Initialize();
                }
                slog("PetBattle_PvP: {0}", _BBSettings.DoPVP);
                //slog("PetFighter uses the CombatRoutine from " + _Pokebuddy.Name);
                //slog(" ©" + _Pokebuddy.Name + " - v" + _Pokebuddy.Version.ToString() + "  by " + _Pokebuddy.Author);
                slog(".. started!");
                slog("");

                startTime = DateTime.Now;
            }

            dlogSettings();
            //try
            //{
            //    dlog("#############################");
            //    for (int i = 1; i <= 3; i++)
            //    {
            //        _Pokebuddy.LoadPetSettings(PetBattle.GetPetLoadOutInfo(i)[0]);
            //        string dumdum = Pokehbuddy.PetSettings.Logic;
            //        string[] PetLogics = dumdum.Split('·');

            //        dlog("######## Logic Pet " + i + " ########");
            //        foreach (string _logic in PetLogics)
            //            dlog(LogLevel.Diagnostic, _logic);
            //    }
            //    dlog("#############################");
            //}
            //catch (Exception ex)
            //{ dlog(LogLevel.Diagnostic, ex.ToString()); }
        }

        public override void Stop()
        {
            if (!_MixedMode)
            {
                double _static1 = (Battle_WON + Battle_lost) / ((DateTime.Now - startTime).TotalMinutes / 60);
                double _static2 = (Battle_WON) / ((DateTime.Now - startTime).TotalMinutes / 60);
                slog("");
                slog("#####################");
                slog("stopped after [{0}]", (DateTime.Now - startTime).ToString().Remove(8));
                slog("");
                slog("Statistics:");
                slog("Battles  won: {0}", Battle_WON);
                slog("Battles lost: {0}", Battle_lost);
                slog("Average {0} Battles/h", _static1.ToString().Split(',')[0]);
                slog("Average {0} Winnings/h", _static2.ToString().Split(',')[0]);
                slog("");
                slog("#####################");
                slog("");

            }
            Lua.Events.DetachEvent("PET_BATTLE_PET_ROUND_RESULTS", RoundResultEvent);
        }

        private void RoundResultEvent(object sender, LuaEventArgs args)
        {
            Round = Convert.ToInt32(args.Args[0]);
        }

        public override Composite Root
        {
            get
            {
                return _root ?? (_root =
                    new PrioritySelector(

                #region <startUp Composite>
                    //new Decorator(ret => startUp,
                    //        new Action(ret => startUp = false)),

                        new Decorator(ret => Me == null || !StyxWoW.IsInGame || !StyxWoW.IsInWorld,
                            new Sequence(
                                new ActionSetActivity("[INVALID] Waiting.."),
                                //new Action(ret => dlog("[INVALID] Waiting..")),
                                new Wait(3, ret => false, new ActionAlwaysSucceed()))),

                        new Decorator(ret => Me.IsDead || Me.IsGhost,
                            new Sequence(
                                new ActionSetActivity("[Death] .."),
                                //new Action(ret => dlog("[Death] CreateDeathBehavior")),
                                Bots.Grind.LevelBot.CreateDeathBehavior())),

                        new Decorator(ret => Me.OnTaxi || Me.IsOnTransport,
                            new Sequence(
                                new ActionSetActivity("[On Taxi] Waiting.."),
                                //new Action(ret => dlog("[On Taxi] Waiting..")),
                                 new Wait(10, ret => false, new ActionAlwaysSucceed()))),

                        new Decorator(ret => PetFighterSettings.Instance.CheckForUpdates && (DateTime.Now - DateTime.FromBinary(PetFighterSettings.Instance.LastUpdateCheck)).TotalHours >= 12 && !UpdateThread.IsAlive,
                            new Action(ret => { UpdateThread.Start();})),                

                        new Decorator(ret => Me.Combat && !Me.Mounted && !PetBattle.IsInPetBattle,
                            new Sequence(
                                new ActionSetActivity("[Combat] Fighting.."),
                                //new Action(ret => dlog("[Combat] Fighting..")),
                                new PrioritySelector(
                                    new Decorator(ret => RoutineManager.Current.NeedHeal,
                                        RoutineManager.Current.HealBehavior),
                                    new Decorator(ret => RoutineManager.Current.NeedCombatBuffs,
                                        RoutineManager.Current.CombatBuffBehavior),
                                    new Decorator(ret => Me.GotTarget && (Me.CurrentTarget.IsPetBattleCritter || Me.CurrentTarget.IsFriendly || Me.CurrentTarget.IsDead),
                                        new Action(ret => Me.ClearTarget())),
                                    //new Decorator(ret => Me.GotTarget && !Me.CurrentTarget.IsFriendly,
                                        RoutineManager.Current.CombatBehavior) // )
                                        )),

                        new Decorator(ret => RoutineManager.Current.NeedPreCombatBuffs && !PetBattle.IsInPetBattle,
                            RoutineManager.Current.PreCombatBuffBehavior),

                        new Decorator(ret => RoutineManager.Current.NeedRest && !PetBattle.IsInPetBattle,
                            new Sequence(
                                new ActionSetActivity("[NeedRest] .."),
                                new Action(ret => RoutineManager.Current.Rest()))),

                        //new Decorator(ret => _needSettingsEditCheck,
                    //    new Action(ret => CombatRoutineHelpers.NeedSettingsEdit() )),
                #endregion

                #region PvP Matchmaking
                        new Decorator(ret => _BBSettings.DoPVP,
                            new Sequence(
                                new Action(ret => dlog("[PvP Matchmaking] .. ")),
                                new PrioritySelector(

                                    new Decorator(ret => PetBattle.GetPVPMatchmakingInfo == null && PetBattleStateByName == "wait" && !PetBattle.IsInPetBattle,
                                        new Sequence(                                            
                                            //new Action(ret => slog("start PvP Matchmaking!")),
                                            new ActionSetActivity("waiting for PvP-Match .."),
                                            new Action(ret => {
                                                #region credits Pokehbuddy
                                                if (_BBSettings.DoPVP && !PetBattle.IsInPetBattle){
                                                Lua.DoString("if C_PetBattles.GetPVPMatchmakingInfo()=='proposal' then C_PetBattles.AcceptQueuedPVPMatch() end");
			
                                                //BBLog("Queue after"+pvptimer+ "now at"+timer.ElapsedMilliseconds/600);
                                                if (pvptimer < 1) {
			
                                                 Random _ran = new Random();
                                                  //BBLog("Queue"+(Pokehbuddy.MySettings.PVPMaxTime+1)*100);
                                                 pvptimer = _ran.Next((_BBSettings.PVPMinTime+1)*100, ((_BBSettings.PVPMinTime+1)+_BBSettings.PVPMaxTime+1)*100);
			
                                                 Logging.Write(Colors.Firebrick, "[BB] new timer set" + pvptimer.ToString()+"  "+ _BBSettings.PVPMinTime +"  "+100*(_BBSettings.PVPMinTime+1+_BBSettings.PVPMaxTime+1));
                                                 }
                                                if (timer.ElapsedMilliseconds > pvptimer*600 && pvptimer != 0) {
                                                //BBLog("should Queue");
                                                 Lua.DoString("C_PetBattles.StartPVPMatchmaking()");
                                                 timer.Reset();
                                                 timer.Start();
			 
                                                 pvptimer = 0;
			 
                                                 }
                                                }
                                                #endregion
                                            }),
                                            new Wait(1, ret => false, new ActionAlwaysSucceed())))
                                            

                                    //new Decorator(ret => PetBattle.GetPVPMatchmakingInfo == "proposal",
                                    //    new Sequence(
                                    //        new Action(ret =>
                                    //        {
                                    //            TimeSpan _rnd = TimeSpan.FromMilliseconds(new Random().Next(1500, 3500));
                                    //            slog(Colors.OrangeRed, "new PetBattle available! Accept match in {0} .. ", _rnd.ToString().Remove(8)); Thread.Sleep(_rnd);
                                    //        }),
                                    //        new Action(ret => PetBattle.AcceptQueuedPVPMatch())))
                                ))),
                #endregion

                WildBattleBehavior(),

                CombatBehavior()
));
            }
        }

        #region WildBattleBehavior
        private Decorator WildBattleBehavior()
        {
            return new Decorator(ret => !PetBattle.IsInPetBattle,
                new PrioritySelector(

                    new Decorator(ret => PetFighterSettings.Instance.PetBattle_Wild,
                        new PrioritySelector(

                            #region Revival
                            new Decorator(ret => PetFighterSettings.Instance.autoRevive && NeedRevival && !PetBattle.IsInPetBattle, 
                                new Sequence(
                                    new Action(ret => dlog("[NeedRevival] ..")),
                                    //new ActionSetActivity("need Revival .."),
                                    new PrioritySelector(

                                        new Decorator(ret => SpellManager.CanCast(ReviveBattlePets),
                                            new Action(ret => { SpellManager.Cast(ReviveBattlePets); Thread.Sleep(400); })),

                                        new Decorator(ret => !SpellManager.CanCast(ReviveBattlePets) && (!PetFighterSettings.Instance.useStablemaster || XmlHelper.StableMaster_getNextStablemaster == null || (XmlHelper.StableMaster_getNextStablemaster != null && ReviveBattlePets.CooldownTimeLeft < TimeSpan.FromSeconds(90))),
                                            new Sequence(
                                                //CreateMountUpBehavior,
                                                new Action(ret => slog("{0} is not available (or CooldownTimeLeft < 90sec)! ready at [{1}]clock ..", ReviveBattlePets.Name, DateTime.Now.Add(ReviveBattlePets.CooldownTimeLeft).ToLongTimeString())),
                                                new ActionSetActivity(ReviveBattlePets.Name + " is not available! Wait " + ReviveBattlePets.CooldownTimeLeft.Minutes + ":" + ReviveBattlePets.CooldownTimeLeft.Seconds + " .."),
                                                //new Action(ret => Flightor.MoveTo(new WoWPoint(Me.Location.X, Me.Location.Y, (Me.Location.Z + 100)))),

                                                new Wait(ReviveBattlePets.CooldownTimeLeft, ret => SpellManager.CanCast(ReviveBattlePets) || Me.Combat, new Action(ret => { })))),

                                        new Decorator(ret => !SpellManager.CanCast(ReviveBattlePets) && PetFighterSettings.Instance.useStablemaster && XmlHelper.StableMaster_getNextStablemaster != null,
                                            new Sequence(
                                                //new ActionSetActivity(ReviveBattlePets.Name + " is not available! Moving to Stablemaster [" + XmlHelper.StableMaster_getNextStablemaster.Name + "] - dis: " + Me.Location.Distance2D(XmlHelper.StableMaster_getNextStablemaster.Location).ToString()),
                                                new ActionSetActivity(ReviveBattlePets.Name + " is not available! Moving to Stablemaster .. "),
                                                new PrioritySelector(


                                                    new Decorator(ret => Me.Location.Distance(XmlHelper.StableMaster_getNextStablemaster.Location) > 8,
                                                        new PrioritySelector(

                                                            CreateMountUpBehavior,

                                                            new Decorator(ret => Me.Mounted,
                                                                new Action(ret => Flightor.MoveTo(XmlHelper.StableMaster_getNextStablemaster.Location))) )),

                                                    new Decorator(ret => Me.Location.Distance(XmlHelper.StableMaster_getNextStablemaster.Location) <= 8,
                                                        new PrioritySelector(

                                                            //new Decorator(ret => Me.Mounted,
                                                            //    new Sequence(
                                                            //        new ActionSetActivity("[PetFighter] Dismount .."),
                                                            //        new Action(ret => dlog("[Dismount] mounted = {0}", Me.Mounted)),
                                                            //        new Action( ret => Lua.DoString("Dismount()")),
                                                            //        new Wait( 3, ret => Me.Mounted || Me.IsFalling, new ActionIdle()) )), 

                                                            new Decorator(ret => /*!Me.Mounted*/ true,
                                                                new Action(ret => UseStablemaster()))

                                                        )))))
                                    ))),
                                #endregion

                            new Decorator(ret => !NextPetBattleCritter,
                                new Sequence(
                                    new Action(ret => dlog("[No PetBattle] ..")),
                                    ProfileHelper.CreatePathBehavior()
                                )),

                            new Decorator(ret => NextPetBattleCritter,
                                new Sequence(
                                    new Action(ret => dlog("[Move To PetBattle] ..")),
                                    new Decorator(ret => PetBattleStateByName == "wait",
                                        CreateMoveToPetBattleCritter())
                                    ))
                                ))
                        ));
                
        }
        #endregion

        #region IsInPetBattle
        private Decorator CombatBehavior()
        {
            return new Decorator(ret => PetBattle.IsInPetBattle,
                    new Sequence(
                        new Action(ret => dlog("[In PetBattle] IsWildBattle = {0} - NewRound = {1}", PetBattle.IsWildBattle, NewRound)),
                        new Action(ret => hasSwap = false),
                        new PrioritySelector(

                            new Decorator(ret => PetBattleStateByName == "endFight",
                                new PrioritySelector(

                                    new Decorator(ret => !giveUp && (PetBattle.GetHealthBySlotID_Me(1) + PetBattle.GetHealthBySlotID_Me(2) + PetBattle.GetHealthBySlotID_Me(3)) != 0,
                                        new Sequence(
                                            new ActionSetActivity("[PetFighter] Battle WON!"),
                                            new Action(ret => slog("Battle WON!")),
                                            new Action(ret => Battle_WON++),
                                            new Action(ret => _nextPetBattleCritter = null),
                                            new Action(ret => Thread.Sleep(4000))
                                            //new Wait(4, ret => false, new ActionAlwaysSucceed())
                                            )),

                                    new Decorator(ret => (PetBattle.GetHealthBySlotID_Me(1) + PetBattle.GetHealthBySlotID_Me(2) + PetBattle.GetHealthBySlotID_Me(3)) == 0 || giveUp,
                                        new Sequence(
                                            new ActionSetActivity("[PetFighter] Battle lost..."),
                                            new Action(ret => slog("Battle lost...")),
                                            new Action(ret => Battle_lost++),
                                            new Action(ret => giveUp = false),
                                            new Action(ret => _nextPetBattleCritter = null),
                                            new Action(ret => Thread.Sleep(4000))
                                            //new Wait(4, ret => false, new ActionAlwaysSucceed())
                                            ))

                                        )),

                            new Decorator(ret => PetBattleStateByName == "startFight",
                                new Sequence(
                                    new Action(ret => dlog("[NewRound] reset all")),
                                    new Action(ret => Round = 0),
                                    new Action(ret => NewRound = false),

                                    new Decorator(ret => !PetBattle.IsWildBattle,
                                        new Sequence(
                                            new ActionSetActivity("[PetFighter] (PvP Battle) StartFight, change Pet to {0} ..", PetBattle.GetPetInfoBySlotID(PetFighterSettings.Instance.PvPStartPetSlotID)[7]),
                                            //new Action(ret => slog("(PvP Battle) StartFight, change Pet to {0} ..", PetFighterSettings.Instance.StartPetSlotID)), //TODO Namen schreiben
                                            new WaitContinue(TimeSpan.FromMilliseconds(1520), ret => false, new ActionAlwaysSucceed()),
                                            new Action(ret => PetBattle.ChangePetBySlotID(PetFighterSettings.Instance.PvPStartPetSlotID))))
                                    )),

                            new Decorator(ret => Round != 0 && PetBattle.ShouldShowPetSelect,
                                new Sequence(
                                    new ActionSetActivity("[PetFighter] PetSelect is shown! wait 3sec .."),
                                    new WaitContinue(TimeSpan.FromSeconds(3), ret => false, new ActionAlwaysSucceed()),
                                    new Wait(3, ret => !PetBattle.ShouldShowPetSelect, new Sequence(                                        
                                        new Action(ret => _PokehbuddygApi.Pulse()),
                                        new Action(ret => Thread.Sleep(100))
                                        ))
                                    
                                    )),


                            new Decorator(ret => PetBattle.IsWaitingToFight,
                                new Sequence(
                                    new ActionSetActivity("[PetFighter] Waiting .."),
                                    //new Action(ret => slog("Waiting for round start ..")),
                                    //new Wait(2, ret => !CombatRoutineHelpers.NewRound, new ActionIdle()),
                                    new Decorator(ret => NewRound && PetBattle.GetSelectedAction != null,
                                        new Sequence(
                                            new Action(ret => dlog("[GetSelectedAction] ..")),
                                            new Action(ret => NewRound = false),
                                            new Action(ret => CreateSelectedAction(PetBattle.GetSelectedAction))
                                            //new Wait(3, ret => PetBattle.IsWaitingToFight, new Action(ret => {}))
                                    ))
                                )),

                            new Decorator(ret => !PetBattle.IsWaitingToFight,
                                new Sequence( 
                                    new ActionSetActivity("[PetFighter] do action .."), 
                                new PrioritySelector(

                                    new Decorator(ret => !NewRound /*&& !waitTimer.IsRunning */,
                                        new Sequence(                               
                                            new Action(ret => NewRound = true), 
                                            new Decorator(ret => PetFighterSettings.Instance.WaitTime != 0,
                                                new Sequence(
                                                    new Action(ret => slog("wait {0}sec before any action will be taken..", PetFighterSettings.Instance.WaitTime)),
                                                    //new Action(ret => Thread.Sleep(TimeSpan.FromSeconds(PetFighterSettings.Instance.WaitTime)))
                                                    new Action(ret => {
                                                    for(int i = PetFighterSettings.Instance.WaitTime; i > 0 && !PetBattle.IsWaitingToFight; i--)
                                                    {
                                                        slog("{0}sec ..", i);
                                                        Thread.Sleep(TimeSpan.FromSeconds(1));
                                                    }
                                            
                                                    })
                                                ))
                                        )),


                                    new Decorator(ret => PetBattle.IsWildBattle && PetBattle.IsTrapAvailable && PetFighterSettings.Instance.TrapIfNeed && !PetBattle.isOwned,
                                        //new PrioritySelector(

                                               
                                              //new Decorator(ret => PetFighterSettings.Instance.TrapIfNeed && !PetBattle.isOwned,
                                                new Sequence(
                                                    //new ActionSetActivity("[PetFighter] Trap is Available! Need [{0}], trying to catch..", PetBattle.GetNameBySlotID_Enemy(PetBattle.GetActivePetSlod_Enemy)),
                                                    new Action(ret => slog("[Trap] Trap is Available! Need [{0}], trying to catch..", PetBattle.GetNameBySlotID_Enemy(PetBattle.GetActivePetSlod_Enemy))),
                                                    new Action(ret => PetBattle.UseTrap()),
                                                    new Action(ret => Thread.Sleep(400)) )),
                                                    //new Wait(2, ret => !PetBattle.IsWaitingToFight, new ActionIdle()) )),

                                                //        new Decorator(ret => PetFighterSettings.Instance.TrapAll,
                                                //new Sequence(
                                                //    //new ActionSetActivity("[PetFighter] Trap is Available! Trying to catch [{0}]..", PetBattle.GetNameByPetID(PetBattle.GetActivePetID_Enemy)), //TODO name
                                                //    new Action(ret => slog("[Trap] Trap is Available! Trying to catch..")),
                                                //    new Action(ret => PetBattle.UseTrap() ),
                                                //    new Wait(2, ret => !PetBattle.IsWaitingToFight, new ActionIdle()) )),
                                            //)),

                                    new Decorator(ret => mustGiveUp,
                                        new Action(ret =>
                                        {
                                            Thread.Sleep(600);
                                            if (PetBattleStateByName != "endFight")
                                            {
                                                slog(Colors.OrangeRed, "Give up match.. all Pets are less then {0}%HP", PetFighterSettings.Instance.GiveUpAt);
                                                giveUp = true; PetBattle.ForfeitGame(); Thread.Sleep(500);
                                            }
                                        })),

                                    new Decorator(ret => PetBattleStateByName == "wait"/* && !waitTimer.IsRunning*/,
                                        CreateCombatRoutines())


                                ))))));
                
        }
        #endregion

        private void UseStablemaster()
        {
            WoWUnit _sMaster = null;
            foreach(WoWUnit unit in ObjectManager.GetObjectsOfType<WoWUnit>())
                if (unit.Entry == XmlHelper.StableMaster_getNextStablemaster.Entry)
                {
                    _sMaster = unit;
                    break;
                }

            if (_sMaster == null)
            { slog(Colors.Red, "Stablemaster not found ?!?"); return; }

            _sMaster.Interact();
            Thread.Sleep(1500);
            Styx.CommonBot.Frames.GossipFrame.Instance.SelectGossipOption(1);
            Thread.Sleep(800);

            if (Lua.GetReturnVal<bool>("return StaticPopup1:IsVisible()", 0))
            {
                Lua.DoString("StaticPopup1Button1:Click()");
                Thread.Sleep(400);
            }
            else
            {
                slog("Stablemaster is busy ?!? wait 10sec ..");
                Styx.CommonBot.Frames.GossipFrame.Instance.Hide();
                Thread.Sleep(10000);
            }

            
        }

        private bool mustGiveUp
        {
            get
            {
                int count = 0;

                for (int i = 1; i <= 3; i++)                
                    if (PetBattle.GetHealthPercent_Me(i) <= PetFighterSettings.Instance.GiveUpAt)
                        count++;

                if (count == 3)
                    return true;

                return false;
            }
            
        }

        private bool NeedRevival
        {
            get
            {
                try
                {
                    if (!SpellManager.HasSpell(ReviveBattlePets))
                    {
                        slog(Colors.Red, "Spell not found - \"Revive Battle Pets\"");
                        dlog("[NeedRevival] spell not found - {0}", ReviveBattlePets.Name);
                        return false;
                    }
                    #region cedits Pokehbuddy
                    //do i actually need heals? by Team Random
                    int dumdum2 = 0;
                    if (_PokehbuddygApi.GetPetHPPreCombat(1) <= PetFighterSettings.Instance.GiveUpAt) dumdum2++;
                    if (_PokehbuddygApi.GetPetHPPreCombat(2) <= PetFighterSettings.Instance.GiveUpAt) dumdum2++;
                    if (_PokehbuddygApi.GetPetHPPreCombat(3) <= PetFighterSettings.Instance.GiveUpAt) dumdum2++;
                    if (dumdum2 > 2)
                    {
                        Logging.Write(Colors.Firebrick, "[BB] " +_PokehbuddygApi.GetPetHPPreCombat(1) + "Injured pets quite high: " + dumdum2 + " Making sure its not due to lag");
                        Lua.DoString("local dummy = C_PetJournal.PetIsHurt(1)");
                        Lua.DoString("local dummy = C_PetJournal.PetIsHurt(2)");
                        Lua.DoString("local dummy = C_PetJournal.PetIsHurt(3)");
                        dumdum2 = 0;
                        if (_PokehbuddygApi.GetPetHPPreCombat(1) <= PetFighterSettings.Instance.GiveUpAt) dumdum2++;
                        if (_PokehbuddygApi.GetPetHPPreCombat(2) <= PetFighterSettings.Instance.GiveUpAt) dumdum2++;
                        if (_PokehbuddygApi.GetPetHPPreCombat(3) <= PetFighterSettings.Instance.GiveUpAt) dumdum2++;
                    }
                    //Heal
                    if (dumdum2 > 0)
                    {
                        //SpellManager.Cast("Revive Battle Pets");
                        Logging.Write(Colors.Firebrick, "[BB] At least 1 pet injured, Healing/Rezzing pets");
                        //Thread.Sleep(300);
                        return true;
                    }
                    #endregion
                }
                catch(Exception ex)
                {dlog(ex.ToString());}
                return false;
            }
        }

        private Composite CreateCombatRoutines()
        {
            return new Sequence(
                new Action(ret => dlog("[PetBattle] Auto Routine..")),
                new Action(ret => {
                    //if (!_Pokébuddy.PetCanCast(1) && !_Pokébuddy.PetCanCast(2) && !_Pokébuddy.PetCanCast(3))
                    //{
                    //    slog("[AUTO] skip this round!"); Lua.DoString("C_PetBattles.SkipTurn()");
                    //}
                    _PokehbuddygApi.Pulse(); 
                })

            );
        }

        private Composite CreateMoveToPetBattleCritter()
        {
            return new Sequence(
                    new Action(ret => dlog("Composit CreateMoveToPetBattleCritter - ")),
                    new PrioritySelector(

                        new Decorator(ret => _nextPetBattleCritter != null && _nextPetBattleCritter.IsPetBattleCritter && Me.Location.Distance(_nextPetBattleCritter.Location) <= 14,
                            new PrioritySelector(

                                new Decorator(ret => Me.Mounted,
                                    new Sequence(
                                        new ActionSetActivity("[PetFighter] Dismount .."),
                                        //new Action(ret => dlog("[Dismount] mounted = {0}", Me.Mounted)),
                                        new Action(ret => WoWMovement.MoveStop()),
                                        new Action(ret => Thread.Sleep(500)),
                                        //new Action( ret => Lua.DoString("Dismount()")),
                                        new Action(ret => Flightor.MountHelper.Dismount()),
                                        new Action(ret => Thread.Sleep(500)) )),

                                        

                                new Decorator(ret => !Me.Mounted /*&& !Me.IsFalling*/,
                                    new PrioritySelector(

                                        new Decorator(ret => PetFighterSettings.Instance.LevelMode,
                                            new Action(ret => _PokehbuddygApi.Pulse())
                                        ),

                                        new Decorator(ret => ! PetFighterSettings.Instance.LevelMode,
                                            new Sequence(
                                                new ActionSetActivity("[PetFighter] Interact .."),
                                                //new Action(ret => dlog("[Interact] ..")),
                                                //new Action(ret => dlog("[Interact] {0} ", PetBattleCritter.Name)),
                                                new Action(ret => _nextPetBattleCritter.Interact()),
                                                new Action(ret => BlacklistCounter++),
                                                new Action(ret => Thread.Sleep(500)),
                                                new Decorator(ret => !PetBattle.IsInPetBattle && BlacklistCounter >  _BBSettings.BlacklistCounterLimit,
                                                    new Action(ret => { slog(Colors.OrangeRed, "Blacklisting [{0}] after {1} try", _nextPetBattleCritter.Name, BlacklistCounter); 
                                                        Blacklist.Add(_nextPetBattleCritter.Guid, TimeSpan.FromMinutes(2)); BlacklistCounter = 0; }))
                                           ))
                                )))),

                        new Decorator(ret => _nextPetBattleCritter != null && _nextPetBattleCritter.IsPetBattleCritter && StyxWoW.Me.Location.Distance(_nextPetBattleCritter.Location) > 12.5,
                            new Sequence(
                                new Action(ret => dlog("[Move To] mounted = {0}", Me.Mounted)),
                                new PrioritySelector(

                                    new Decorator(ret => Me.Mounted,
                                        new Sequence(
                                            new ActionSetActivity("[PetFighter] FlyTo PetBattle"),
                                            new Action(ret => dlog("[FlyTo] Pet dis: {0}", Me.Location.Distance(_nextPetBattleCritter.Location))),
                                            new Action(ret => Flightor.MoveTo(_nextPetBattleCritter.Location))                                        
                                        )),

                                    new Decorator(ret => !Me.Mounted && StyxWoW.Me.Location.Distance(_nextPetBattleCritter.Location) <= 30 && Navigator.CanNavigateFully(Me.Location, _nextPetBattleCritter.Location),
                                        new Sequence(
                                            new ActionSetActivity("[PetFighter] MoveTo PetBattle"),
                                            new Action(ret => dlog("[MoveTo] Pet dis: {0}", Me.Location.Distance(_nextPetBattleCritter.Location))),
                                            new Action(ret => Navigator.MoveTo(_nextPetBattleCritter.Location))
                                        )),

                                    CreateMountUpBehavior
                        )))
                    ));
        }

        public static Decorator CreateMountUpBehavior
        {
            get
            {
                return new Decorator(ret => !Me.Mounted,
                        new Sequence(
                            new ActionSetActivity("[PetFighter] MountUp .."),
                            //new Action(ret => dlog("[MountUp] ..")),
                            new Action(ret => Flightor.MountHelper.MountUp()),
                            new Wait(2, ret => !Me.Mounted, new ActionIdle()))
                            );
            }
        }

        private bool lvlOk(WoWUnit unit)
        {
            unit.Target();
            Thread.Sleep(300);
            if (_PokehbuddygApi.GetWildLevel() > _PokehbuddygApi.GetLowLevel() - (_BBSettings.BelowLevel + 1) && _PokehbuddygApi.GetWildLevel() < _PokehbuddygApi.GetHighLevel() + _BBSettings.AboveLevel + 1)
            {
                return true;
            }
            else
            {
                Blacklist.Add(unit.Guid, BlacklistFlags.All, TimeSpan.FromMinutes(1));
            }
            return false;
        }

        private WoWUnit _nextPetBattleCritter = null; 
        private WoWUnit getNextPetBattleCritter
        {
            get
            {
                try
                {
                    ObjectManager.Update();
                    WoWUnit ret = (from unit in ObjectManager.GetObjectsOfType<WoWUnit>(true, true)
                                   orderby unit.Distance ascending

                                   where unit.IsPetBattleCritter
                                   where !unit.IsDead
                                   where lvlOk(unit)
                                   where !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                                   where unit.Distance < _BBSettings.Distance
                                   select unit).FirstOrDefault();
                    _nextPetBattleCritter = ret;
                    return ret;
                }
                catch (Exception ex)
                {
                    Logging.WriteException(Colors.Firebrick, ex);
                    _nextPetBattleCritter = null;
                    return null;
                }
            }
        }

        private bool NextPetBattleCritter
        {
            get
            {
                if (getNextPetBattleCritter == null)
                    return false;
                return true;
            }
        }

        /// <summary>
        /// ("startFight", "endFight", "needPet" or "wait")
        /// </summary>
        private string PetBattleStateByName
        {
            // 2 = fight start
            // 3 = waiting... ?!
            // 4 = pet deatch / (need pet)
            // 7 = fight ende
            get
            {
                string _State = PetBattle.PetBattleState.ToString();

                switch (_State)
                {
                    case "2":
                        _State = "startFight";
                        break;
                    case "7":
                        _State = "endFight";
                        break;
                    case("4"):
                        _State = "needPet";
                        break;
                    default:
                        if (_State != "3")
                            Styx.Common.Logging.Write(System.Windows.Media.Colors.Red, "UNNKNOWN BattleState \n  state = {0}", _State);
                        _State = "wait";
                        break;
                }

                return _State;
            }
        }

        private static void checkUpdates()
        {
            try
            {
                PetFighter.slog(Colors.GreenYellow, "Checking for Updates.."); 
                PetFighterSettings.Instance.LastUpdateCheck = DateTime.Now.ToBinary();
                System.Net.WebClient wClient = new System.Net.WebClient();
                PetFighter.dlog("webClint rdy");
                string strSource = wClient.DownloadString("http://petfighter.googlecode.com/svn/trunk/Version.txt");

                if (PetFighter._Version < new Version(strSource))
                {
                    System.Media.SystemSounds.Question.Play();
                    PetFighter.slog(Colors.GreenYellow, "a new version is available!");

                    string _msg = string.Format("a new version is available! \n Version: {0} \n\nDo you want to update now?", strSource);

                    if (MessageBox.Show(_msg, "[PetFighter]", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
                    { HighVoltz.Updater.CheckForUpdate(); System.Diagnostics.Process.Start(PetFighter.ForumLink); }
                }
                else
                    PetFighter.slog(Colors.GreenYellow, "you are up to date!");
            }
            catch (Exception ex)
            {
               Logging.WriteException(Colors.Firebrick, ex);
            }
        }

        public void dlogSettings()
        {            
            dlog("---------------------");
            dlog("-------Settings------");
            dlog("PetBattle_Wild   : {0}", PetFighterSettings.Instance.PetBattle_Wild);
            dlog("LevelMode        : {0}", PetFighterSettings.Instance.LevelMode);
            dlog("autoRevive       : {0}", PetFighterSettings.Instance.autoRevive);
            dlog("useStablemaster  : {0}", PetFighterSettings.Instance.useStablemaster);
            dlog("GiveUpAt         : {0}", PetFighterSettings.Instance.GiveUpAt);
            dlog("TrapIfNeed       : {0}", PetFighterSettings.Instance.TrapIfNeed);
            dlog("WaitTime         : {0}", PetFighterSettings.Instance.WaitTime);
            dlog("CheckForUpdates  : {0}", PetFighterSettings.Instance.CheckForUpdates);
            dlog("LastUpdateCheck  : {0}", DateTime.FromBinary(PetFighterSettings.Instance.LastUpdateCheck));
            dlog("useNotifyIcon    : {0}", PetFighterSettings.Instance.useNotifyIcon);
            dlog("ProfileRnd       : {0}", PetFighterSettings.Instance.ProfileRnd);
            dlog("ProfileCir       : {0}", PetFighterSettings.Instance.ProfileCir);
            dlog("ProfileBou       : {0}", PetFighterSettings.Instance.ProfileBou);
            dlog("---------------------");
            dlog("------Pokehbuddy-----");
            dlog("---------------------");
            dlog("AboveLevel               : {0}", _BBSettings.AboveLevel);
            dlog("AdFactor                 : {0}", _BBSettings.AdFactor);
            dlog("AmHorde                  : {0}", _BBSettings.AmHorde);
            dlog("BelowLevel               : {0}", _BBSettings.BelowLevel);
            dlog("BlacklistCounterLimit    : {0}", _BBSettings.BlacklistCounterLimit);
            dlog("DisFactor                : {0}", _BBSettings.DisFactor);
            dlog("Distance                 : {0}", _BBSettings.Distance);
            dlog("DoPVP                    : {0}", _BBSettings.DoPVP);
            dlog("ForfeitIfNotInteresting  : {0}", _BBSettings.ForfeitIfNotInteresting);
            dlog("GetRarity                : {0}", _BBSettings.GetRarity);
            dlog("HPFactor                 : {0}", _BBSettings.HPFactor);
            dlog("IBSupport                : {0}", _BBSettings.IBSupport);
            dlog("LevelFactor              : {0}", _BBSettings.LevelFactor);
            dlog("MailEveryReset           : {0}", _BBSettings.MailEveryReset);
            dlog("PVPMaxTime               : {0}", _BBSettings.PVPMaxTime);
            dlog("PVPMinTime               : {0}", _BBSettings.PVPMinTime);
            dlog("SkipCounterLimit         : {0}", _BBSettings.SkipCounterLimit);
            dlog("UseBandages              : {0}", _BBSettings.UseBandages);
            dlog("---------------------");
            dlog("---------------------");
        }

        public static void CreateSelectedAction(List<string> Action)
        {
            string txt = string.Empty;
            // PetChange[3/(Pet1=2,Pet2=3,Pet3=4)] - Action[2/(Abili1=1,Abili2=2,Abili3=3)] - skip[5/1] - trap[4/1]
            switch (Action[0])
            {
                case ("2"): // Action[2/(Abili1=1,Abili2=2,Abili3=3)]
                    txt = string.Format("selected action was: (Ability) [{0}]", PetBattle.GetAbilityInfo_Me(PetBattle.GetActivePetSlod_Me, Convert.ToInt32(Action[1]))[1]);
                    break;
                case ("3"): // PetChange[3/(Pet1=2,Pet2=3,Pet3=4)]
                    var pet = PetBattle.GetPetInfoBySlotID((Convert.ToInt32(Action[1]) - 1));
                    string name = pet[1];
                    if (name == "nil")
                        name = pet[7];
                    txt = string.Format("selected action was: change Pet to [{0}]", name);
                    break;
                case ("4"): // trap[4/1]
                    txt = string.Format("selected action was: use Trap");
                    break;
                case ("5"): // skip[5/1]
                    txt = string.Format("selected action was: skip this round");
                    break;
                default:
                    slog(System.Windows.Media.Colors.OrangeRed, "selected action was: unknown \nPLEASE REPORT to the forum, which action was taken with the following information [SelectedAction = {0}/{1}]", Action[0], Action[1]);
                    break;
            }

            if (!string.IsNullOrEmpty(txt))
                slog(Colors.PaleGreen, txt);
        }

        #region convertToIcon
        /// <summary>
        /// convert a Image to Icon
        /// </summary>
        /// <param name="image">Image file</param>
        /// <param name="color">Make Transparent</param>
        /// <returns>the Image as Icon</returns>
        public System.Drawing.Icon convertToIcon(System.Drawing.Image image, System.Drawing.Color color)
        {
            System.Drawing.Bitmap _bitmap = (System.Drawing.Bitmap)image;
            if (color != System.Drawing.Color.Empty)
                _bitmap.MakeTransparent(color);
            System.IntPtr _intPtr = _bitmap.GetHicon();
            System.Drawing.Icon _icon = System.Drawing.Icon.FromHandle(_intPtr);
            return _icon;
        }
        #endregion
    }
}
